package com.whmskj.xjlhsc.service.impl;

import cn.hutool.core.util.StrUtil;
import com.whmskj.xjlhbc.db.DataSource;
import com.whmskj.xjlhbc.db.DataSourceType;
import com.whmskj.xjlhbc.db.DynamicDataSourceContextHolder;
import com.whmskj.xjlhsc.controller.fo.ElectricAnalysisFo;
import com.whmskj.xjlhsc.entity.Sb02EquipmentCounterAccount;
import com.whmskj.xjlhsc.mapper.ElectricAnalysisMapper;
import com.whmskj.xjlhsc.service.ElectricAnalysisService;
import com.whmskj.xjlhsc.service.Sb02EquipmentCounterAccountService;
import com.whmskj.xjlhsc.service.dto.DqAnalysisDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Predicate;

/**
 *
 */
@Service
@Slf4j
public class ElectricAnalysisServiceImpl  implements ElectricAnalysisService {

    @Autowired
    private ElectricAnalysisMapper mapper;

    @Autowired
    private Sb02EquipmentCounterAccountService sb02EquipmentCounterAccountService;

    private static final String yyyyMMdd = "yyyyMMdd";

    @Override
    @DataSource(DataSourceType.SC)
    public List<DqAnalysisDto> dqsj(ElectricAnalysisFo fo) {
        getParams(fo);
        return mapper.dqsj(fo);
    }

    @Override
    @DataSource(DataSourceType.SC)
    public DqAnalysisDto.Chart dqqsdb(ElectricAnalysisFo fo) {
        List<DqAnalysisDto> list = dqqsdbList(fo);
        List<String> dateList = getDateList(fo);
        Map<String, List<Double>> dataMap = getDataMap();
        for (String s : dateList) {
            String date = LocalDate.parse(s).format(DateTimeFormatter.ofPattern(yyyyMMdd));
            Predicate<DqAnalysisDto> predicate = item -> Objects.nonNull(item) && StringUtils.hasText(item.getDate()) && item.getDate().equals(date);
            add(dataMap, predicate, list);
        }
        DqAnalysisDto.Chart chart = new DqAnalysisDto.Chart();
        chart.setDateList(dateList);
        chart.setDataList(dataMap);
        return chart;
    }

    @Override
    @DataSource(DataSourceType.SC)
    public List<DqAnalysisDto> dqqsdbList(ElectricAnalysisFo fo) {
        getParams(fo);
        return mapper.dqqsdb(fo);
    }

    @Override
    @DataSource(DataSourceType.SC)
    public DqAnalysisDto.Chart dqjtdb(ElectricAnalysisFo fo) {
        List<DqAnalysisDto> list = dqjtdbList(fo);
        DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
        List<String> machineryToolList = getMachineryToolList();
        Map<String, List<Double>> dataMap = getDataMap();
        for(int i=0;i<machineryToolList.size();i++){
            String machineryTool = machineryToolList.get(i);
            Predicate<DqAnalysisDto> predicate = item -> Objects.nonNull(item) && item.getMachineryTool().equals(machineryTool);
            add(dataMap, predicate,list);
        }
        DqAnalysisDto.Chart chart = new DqAnalysisDto.Chart();
        chart.setDateList(machineryToolList);
        chart.setDataList(dataMap);
        return chart;
    }

    @Override
    @DataSource(DataSourceType.SC)
    public List<DqAnalysisDto> dqjtdbList(ElectricAnalysisFo fo) {
        getParams(fo);
        return mapper.dqjtdb(fo);
    }

    @Override
    @DataSource(DataSourceType.SC)
    public DqAnalysisDto.Chart dqpzdb(ElectricAnalysisFo fo) {
        List<DqAnalysisDto> list = dqpzdbList(fo);
        List<String> varietyNameList = getVarietyNameList();
        Map<String, List<Double>> dataMap = getDataMap();
        for(int i=0;i<varietyNameList.size();i++){
            String name = varietyNameList.get(i);
            Predicate<DqAnalysisDto> predicate = item -> Objects.nonNull(item) && StringUtils.hasText(item.getName()) && item.getName().equals(name);
            add(dataMap, predicate,list);
        }
        DqAnalysisDto.Chart chart = new DqAnalysisDto.Chart();
        chart.setDateList(varietyNameList);
        chart.setDataList(dataMap);
        return chart;
    }

    @Override
    @DataSource(DataSourceType.SC)
    public List<DqAnalysisDto> dqpzdbList(ElectricAnalysisFo fo) {
        getParams(fo);
        return mapper.dqpzdb(fo);
    }

    private List<String> getMachineryToolList(){
        Map<String, List<Sb02EquipmentCounterAccount>> equipmentList = sb02EquipmentCounterAccountService.findEquipmentList();
        List<Sb02EquipmentCounterAccount> list = equipmentList.get("络筒");
        return list.stream().map(m-> getMachineryId(m.getPlatform())).toList();
    }

    private List<String> getVarietyNameList(){
        return List.of("CF40SK");
    }
    private List<String> getDateList(ElectricAnalysisFo fo){
        List<String> dateList = new ArrayList<>();
        List<String> dateRange = fo.getDateRange();
        LocalDate begin = LocalDate.parse(dateRange.get(0),DateTimeFormatter.ofPattern(yyyyMMdd));
        LocalDate end = LocalDate.parse(dateRange.get(1),DateTimeFormatter.ofPattern(yyyyMMdd));
        long days = ChronoUnit.DAYS.between(begin, end);
        for(int i=0;i<=days;i++){
            dateList.add(begin.toString());
            begin = begin.plusDays(1);
        }
        return dateList;

    }

    private void getParams(ElectricAnalysisFo fo){
        String dateYmd = fo.getDateYmd();
        List<String> dateRange = fo.getDateRange();
        boolean beginTime = !dateRange.isEmpty();
        LocalDate end = LocalDate.now();
        LocalDate begin = end.minusDays(30);
        if(beginTime){
            begin = LocalDate.parse(dateRange.get(0));
            end = LocalDate.parse(dateRange.get(1));
        }
        if(StringUtils.hasText(dateYmd)){
            begin = LocalDate.parse(dateYmd);
            end = LocalDate.parse(dateYmd);
        }
        dateRange.add(0,begin.format(DateTimeFormatter.ofPattern(yyyyMMdd)));
        dateRange.add(1,end.format(DateTimeFormatter.ofPattern(yyyyMMdd)));
        List<String> machineryIds = fo.getMachineryIds();
        if(!machineryIds.isEmpty()){
            List<String> ids = new ArrayList<>();
            machineryIds.forEach(f -> ids.add(getMachineryId(f)));
            fo.setMachineryIds(ids);
        }
        fo.setMachineryId(getMachineryId(fo.getMachineryId()));
    }

    private String getMachineryId(String machineryId){
        if(StringUtils.hasText(machineryId)){
            return "M" + StrUtil.fillBefore(machineryId.replace("#", ""), '0', 2);
        }
        return machineryId;
    }

    private Map<String, List<Double>> getDataMap(){
        Map<String, List<Double>> dataMap = new HashMap<>();
        dataMap.put("pef", new ArrayList<>());
        dataMap.put("aef", new ArrayList<>());
        dataMap.put("yf", new ArrayList<>());
        dataMap.put("yj", new ArrayList<>());
        dataMap.put("yb", new ArrayList<>());
        dataMap.put("n", new ArrayList<>());
        dataMap.put("s", new ArrayList<>());
        dataMap.put("l", new ArrayList<>());
        dataMap.put("t", new ArrayList<>());
        dataMap.put("c", new ArrayList<>());
        dataMap.put("c1", new ArrayList<>());
        dataMap.put("c2", new ArrayList<>());
        dataMap.put("cc", new ArrayList<>());
        dataMap.put("cc1", new ArrayList<>());
        dataMap.put("cc2", new ArrayList<>());
        dataMap.put("j", new ArrayList<>());
        dataMap.put("j1", new ArrayList<>());
        dataMap.put("j2", new ArrayList<>());
        dataMap.put("pf", new ArrayList<>());
        dataMap.put("pc", new ArrayList<>());
        dataMap.put("fd", new ArrayList<>());
        dataMap.put("pp", new ArrayList<>());
        dataMap.put("fl", new ArrayList<>());
        return dataMap;
    }

    private void add(Map<String, List<Double>> dataMap,
                     Predicate<DqAnalysisDto> predicate,
                     List<DqAnalysisDto> list){

        dataMap.get("pef").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getPef()) ? Double.parseDouble(item.getPef()) : 0)
                .sum());
        dataMap.get("aef").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getAef()) ? Double.parseDouble(item.getAef()) : 0)
                .sum());
        dataMap.get("yf").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getYf()) ? Double.parseDouble(item.getYf()) : 0)
                .sum());
        dataMap.get("yj").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getYj()) ? Double.parseDouble(item.getYj()) : 0)
                .sum());
        dataMap.get("yb").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getYb()) ? Double.parseDouble(item.getYb()) : 0)
                .sum());
        dataMap.get("n").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getN()) ? Double.parseDouble(item.getN()) : 0)
                .sum());
        dataMap.get("s").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getS()) ? Double.parseDouble(item.getS()) : 0)
                .sum());
        dataMap.get("l").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getL()) ? Double.parseDouble(item.getL()) : 0)
                .sum());
        dataMap.get("t").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getT()) ? Double.parseDouble(item.getT()) : 0)
                .sum());
        dataMap.get("c").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getC()) ? Double.parseDouble(item.getC()) : 0)
                .sum());
        dataMap.get("c1").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getC1()) ? Double.parseDouble(item.getC1()) : 0)
                .sum());
        dataMap.get("c2").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getC2()) ? Double.parseDouble(item.getC2()) : 0)
                .sum());
        dataMap.get("cc").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getCc()) ? Double.parseDouble(item.getCc()) : 0)
                .sum());
        dataMap.get("cc1").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getCc1()) ? Double.parseDouble(item.getCc1()) : 0)
                .sum());
        dataMap.get("cc2").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getCc2()) ? Double.parseDouble(item.getCc2()) : 0)
                .sum());
        dataMap.get("j").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getJ()) ? Double.parseDouble(item.getJ()) : 0)
                .sum());
        dataMap.get("j1").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getJ1()) ? Double.parseDouble(item.getJ1()) : 0)
                .sum());
        dataMap.get("j2").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getJ2()) ? Double.parseDouble(item.getJ2()) : 0)
                .sum());
        dataMap.get("pf").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getPf()) ? Double.parseDouble(item.getPf()) : 0)
                .sum());
        dataMap.get("pc").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getPc()) ? Double.parseDouble(item.getPc()) : 0)
                .sum());
        dataMap.get("fd").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getFd()) ? Double.parseDouble(item.getFd()) : 0)
                .sum());
        dataMap.get("pp").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getPp()) ? Double.parseDouble(item.getPp()) : 0)
                .sum());
        dataMap.get("fl").add(list.stream().filter(predicate)
                .mapToDouble(item -> StringUtils.hasText(item.getFl()) ? Double.parseDouble(item.getFl()) : 0)
                .sum());
    }
}
